#region Using Statements
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
#endregion

namespace FrameRateComponent
{
    /// <summary>
    /// This is a game component that implements IUpdateable.
    /// </summary>
    public class Framerate : Microsoft.Xna.Framework.DrawableGameComponent
    {
        private float deltaFPSTime;
        private double currentFramerate;
        private string windowTitle, displayFormat;
        private bool canDraw, showDecimals;

        public double Current
        {
            get { return this.currentFramerate; }
        }

        public bool IsFixedTimeStep
        {
            get { return this.Game.IsFixedTimeStep; }
            set
            {
                if (this.Game != null)
                    this.Game.IsFixedTimeStep = value;
            }
        }

        public bool ShowDecimals
        {
            get { return this.showDecimals; }
            set { this.showDecimals = value; }
        }

        public bool FixedFormatDisplay
        {
            get { return this.displayFormat == "F"; }
            set { this.displayFormat = value == true ? "F" : "R"; }
        }

        public Framerate(Game game)
            : base(game)
        {
            // TODO: Construct any child components here
        }


        /// <summary>
        /// Allows the game component to perform any initialization it needs to before starting
        /// to run.  This is where it can query for any required services and load content.
        /// </summary>
        public override void Initialize()
        {
            // TODO: Add your initialization code here


            this.Enabled = true;
            this.Visible = true;

            this.currentFramerate = 0;

            if (this.Game != null && this.windowTitle != null && !this.Enabled && !this.Visible)
                this.Game.Window.Title = this.windowTitle;

            this.canDraw = false;
            this.windowTitle = this.Game != null ? this.Game.Window.Title : String.Empty;

            base.Initialize();
        }


        /// <summary>
        /// Allows the game component to update itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public override void Update(GameTime gameTime)
        {
            // TODO: Add your update code here
            if (this.Enabled)
            {
                // The time since Update() method was last called.
                float elapsed = (float)gameTime.ElapsedRealTime.Milliseconds;

                // Ads the elapsed time to the cumulative delta time.
                this.deltaFPSTime += elapsed;

                // If delta time is greater than a second: (a) the framerate is calculated, (b) it is marked to be drawn, and (c) the delta time is adjusted, accordingly.
                if (this.deltaFPSTime > 1000)
                {
                    this.currentFramerate = 1000 / elapsed;
                    this.deltaFPSTime -= 1000;
                    this.canDraw = true;
                }
            }
            base.Update(gameTime);
        }

        public override void Draw(GameTime gameTime)
        {
            // If the framerate can be drawn, it is shown in the window's title of the game.
            if (this.Visible && this.canDraw)
            {
                string currentFramerateString = this.showDecimals ? this.currentFramerate.ToString(this.displayFormat) : ((int)this.currentFramerate).ToString("D");

                this.Game.Window.Title = "FPS: " + currentFramerateString;

                this.canDraw = false;
            }
        } 
    }
}


